package thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author G_Y
 * @Date 2021/3/28 14:36
 * @Description: // TODO
 **/
public class ThreadPoolUseTest {

    public static void main(String[] args) {
        // 初始化待测试的数据
        List<Article> articles = new ArrayList<>(10000);
        for (int i = 0; i < 10000; i++) {
            Article article = new Article(i, 0, 10);
            articles.add(article);
        }

        ThreadPoolUseTest threadPoolUseTest = new ThreadPoolUseTest();
        long time = 0L;
        System.out.println(time = System.currentTimeMillis());
        // 计算得分
        threadPoolUseTest.computeHotArticle(articles);

        System.out.println(System.currentTimeMillis() - time);
        System.out.println(articles.get(9999).getScore());

    }

    private static final ThreadPoolExecutor executor =
            new ThreadPoolExecutor(4, 10, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<>(500),
                    new ThreadPoolExecutor.CallerRunsPolicy());

    static {
        executor.allowCoreThreadTimeOut(true);
    }

    public void computeHotArticle(List<Article> articles) {
        CountDownLatch countDownLatch = new CountDownLatch(articles.size());
        for (Article article : articles) {
            // 计算单个文章得分
//            Integer score = computeHotArticleSingle(article);
//            article.setScore(score);
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 计算单个文章得分
                        Integer score = computeHotArticleSingle(article);
                        article.setScore(score);
                    } finally {
                        countDownLatch.countDown();
                    }
                }
            });
        }
        try {
            countDownLatch.await(); // 如果 线程池中 任务未执行完毕，这里线程将会阻塞
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 在方法执行到这里的时候，要求 所有的 文章得分都已经计算完毕
    }

    public Integer computeHotArticleSingle(Article article) {
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return article.getLikeTimes() * 5;
    }

}

class Article {
    private Integer id;
    private Integer score = 0;
    private Integer likeTimes;

    public Article(Integer id, Integer score, Integer likeTimes) {
        this.id = id;
        this.score = score;
        this.likeTimes = likeTimes;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getScore() {
        return score;
    }

    public void setScore(Integer score) {
        this.score = score;
    }

    public Integer getLikeTimes() {
        return likeTimes;
    }

    public void setLikeTimes(Integer likeTimes) {
        this.likeTimes = likeTimes;
    }
}
